package com.nq.service.impl;

/**

 * 开发者----信达
 * 联系TG：wanxing.wang
 */
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nq.common.ServerResponse;
import com.nq.common.SystemVersionEnum;
import com.nq.common.entity.StStockTickerDetails;
import com.nq.common.entity.info.StockTickerListInfo;
import com.nq.dao.*;
import com.nq.dao.stock.StStockMapper;
import com.nq.pojo.*;
import com.nq.service.*;
import com.nq.stock.entity.StStock;
import com.nq.utils.DateTimeUtil;
import com.nq.utils.PropertiesUtil;
import com.nq.utils.SymmetricCryptoUtil;
import com.nq.utils.redis.JsonUtil;
import com.nq.utils.redis.RedisShardedPoolUtils;
import com.nq.utils.stock.BuyAndSellUtils;
import com.nq.utils.task.tsanghi.StocksComponent;
import com.nq.vo.position.UserPendingorderVO;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;


/**
 * @author Administrator
 * @description 针对表【user_pendingorder】的数据库操作Service实现
 * @createDate 2022-11-10 06:10:40
 */
@Service
@Slf4j
public class UserPendingorderServiceImpl extends ServiceImpl<UserPendingorderMapper, UserPendingorder>
        implements IUserPendingorderService {

    /**
     * 支付密码
     */
    private static final String PAY_PWD_PREFIX = "pay_pwd:";

    @Autowired
    private UserPendingorderMapper userPendingorderMapper;

    @Autowired
    private IUserService iUserService;
    @Autowired
    private IUserPositionService iUserPositionService;
    @Autowired
    private SiteTaskLogMapper siteTaskLogMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ISiteSettingService iSiteSettingService;
    @Resource
    private IStPremarketStockService stPremarketStockService;
    @Resource
    private StStockMapper stStockMapper;
    @Resource
    private StocksComponent stocksComponent;
    @Autowired
    FundsApplyMapper fundsApplyMapper;
    @Resource
    private IUserPositionService userPositionService;

    @Resource
    private UserPositionMapper userPositionMapper;

    @Value("${spring.profiles.active}")
    private String active;

    @Override
    @Transactional
    public ServerResponse addOrder(String stockId,
                                   String market,
                                   Integer buyNum,
                                   Integer buyType,
                                   Integer lever,
                                   BigDecimal profitTarget,
                                   BigDecimal stopTarget,
                                   BigDecimal targetPrice,
                                   HttpServletRequest request,
                                   String payPwd) {
        User user = this.iUserService.getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("请先登录.");
        }
        // 判断挂单数量
        if (buyNum <= 0) {
            return ServerResponse.createByErrorMsg("挂单失败，数值不能为0！");
        }
        // 校验支付密码
        String userPayPwd = user.getPayPwd();
        if (StringUtils.isBlank(userPayPwd)) {
            return ServerResponse.createByErrorMsg("您尚未设置支付密码，请先设置支付密码再进行购买！");
        }

        // 校验密码是否正确
        if (!SymmetricCryptoUtil.encryptPassword(payPwd).equals(userPayPwd)) {
            boolean isLocked = iUserService.isLocked(PAY_PWD_PREFIX, user.getId());
            if (isLocked) {
                return ServerResponse.createByErrorMsg("Purchase failed, The password has exceeded 5 times. Please wait for half an hour before making a purchase.");
            }
            return ServerResponse.createByErrorMsg("Purchase failed, The password you entered is incorrect, please re-enter it!");
        }

        SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
        if (buyNum.intValue() < siteSetting.getBuyMinNum().intValue()) {
            return ServerResponse.createByErrorMsg("The pending order failed, and the purchase quantity was less than " + siteSetting.getBuyMinNum() + "shares");
        }

        if (buyNum.intValue() > siteSetting.getBuyMaxNum().intValue()) {
            return ServerResponse.createByErrorMsg("The pending order failed, and the number of purchases was greater than " + siteSetting.getBuyMaxNum() + "shares");
        }

        //挂单-股票  使用股票新接口
        // 查询该股票的实时价格
        // 使用新版股票数据
        QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
        stockQueryWrapper.eq("code", stockId);
        stockQueryWrapper.eq("market", market);
        StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
        if (null == stStock) {
            return ServerResponse.createByErrorMsg("The order failed, and the stock does not exist.！");
        }

        // 查询该股票的实时价格
        StStockTickerDetails tickerDetails = stocksComponent.queryDetailsByMarketAndCode(market, stockId);
        if (null == tickerDetails) {
            return ServerResponse.createByErrorMsg("Failed to query the real-time price of stocks！【tickerDetails】");
        }

        StockTickerListInfo tickerInfo = tickerDetails.getData();
        if (null == tickerInfo) {
            return ServerResponse.createByErrorMsg("Failed to query the real-time price of stocks！【tickerInfo】");
        }

        // 不用管其他。以我这句话为准： B1=0 表示跌停 不可以卖出 S1=0 表示涨停，不可以买入
//        String s1 = tickerInfo.getS1();
//        if (active.equals(SystemVersionEnum.india.name()) && new BigDecimal(s1).compareTo(BigDecimal.ZERO) == 0) {
//            return ServerResponse.createByErrorMsg("The order failed, The S1 price is currently 0");
//        }

        BigDecimal initPrice = tickerInfo.getPrice();

        BigDecimal nowPrice = initPrice;
        BigDecimal conversionTargetPrice = targetPrice;

        // 判断金额是否够用
        BigDecimal tradingAmount = user.getTradingAmount();
        BigDecimal enableAmt = user.getEnableAmt();
        BigDecimal targetAmount = new BigDecimal(buyNum).multiply(conversionTargetPrice).setScale(6, BigDecimal.ROUND_HALF_UP);
        // 如果配资金额+可用金额小于购买金额，则直接给出提示余额不足
        if (tradingAmount.add(enableAmt).compareTo(targetAmount) < 0) {
            return ServerResponse.createByErrorMsg("The order failed, Insufficient available funds.");
        }

        // 新增挂单记录
        UserPendingorder userPendingorder = new UserPendingorder();
        userPendingorder.setUserId(user.getId());
        userPendingorder.setStockId(stockId);
        userPendingorder.setMarket(market);
        userPendingorder.setBuyNum(buyNum);
        userPendingorder.setBuyType(buyType);
        userPendingorder.setLever(lever);
        userPendingorder.setProfitTarget(profitTarget);
        userPendingorder.setStopTarget(stopTarget);
        userPendingorder.setInitPrice(initPrice);
        userPendingorder.setNowPrice(nowPrice);
        userPendingorder.setTargetPrice(targetPrice);
        userPendingorder.setAddTime(new Date());
        userPendingorder.setStatus(0);
        userPendingorder.setType(1);
        int ret = userPendingorderMapper.insert(userPendingorder);
        if (ret > 0) {
            // 扣除金额，先从配资中扣除，如果不够，再从可用余额扣除剩余的
            // 扣除的金额 = 目标价格 * 数量
            BigDecimal deduction = conversionTargetPrice.multiply(new BigDecimal(buyNum)).setScale(6, BigDecimal.ROUND_HALF_UP);
            boolean b = userPositionService.updateUserAccount(user, deduction);
            if (!b) {
                log.error("挂单买入失败, 用户余额不足, 挂单总金额: " + deduction, "用户可用金额: " + tradingAmount.add(enableAmt));
                throw new IllegalArgumentException("Hang Bill buy failure, the user balance is insufficient!");
            }
            // 将金额补充到冻结资金中
            User userNew = new User();
            userNew.setId(user.getId());
            BigDecimal dj = user.getDjzj().add(deduction).setScale(6, BigDecimal.ROUND_HALF_UP);
            if (dj.compareTo(BigDecimal.ZERO) <= 0) {
                dj = new BigDecimal(BigInteger.ZERO);
            }
            userNew.setDjzj(dj);
            userMapper.updateById(userNew);
            return ServerResponse.createBySuccessMsg("Add a pending order successfully, and the order will be placed automatically if the order conditions are met.");
        }
        return ServerResponse.createByErrorMsg("Failed to add");

    }



    @Override
    public ServerResponse orderList(HttpServletRequest request) {
        User user = this.iUserService.getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        QueryWrapper<UserPendingorder> pendingorderQueryWrapper = new QueryWrapper<UserPendingorder>();
        pendingorderQueryWrapper.eq("user_id", user.getId());
        pendingorderQueryWrapper.eq("status", 0);// 挂单中的
        pendingorderQueryWrapper.orderByDesc("add_time");
        List<UserPendingorder> userPendingorders = userPendingorderMapper.selectList(pendingorderQueryWrapper);

        List UserPendingorderList = new ArrayList();
        for (UserPendingorder userPendingorder : userPendingorders) {
            UserPendingorderVO userPendingorderVO = new UserPendingorderVO();
            //挂单-股票
            String stockId = userPendingorder.getStockId();
            String market = userPendingorder.getMarket();
            QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
            stockQueryWrapper.eq("code", stockId);
            stockQueryWrapper.eq(StringUtils.isNotBlank(market), "market", market);
            StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
            if (null == stStock) {
                continue;
            }

            // 查询该股票的实时价格
            StStockTickerDetails tickerDetails = stocksComponent.queryDetailsByMarketAndCode(stStock.getMarket(), stockId);
            if (null == tickerDetails) {
                continue;
            }

            StockTickerListInfo tickerInfo = tickerDetails.getData();
            if (null == tickerInfo) {
                continue;
            }


            BigDecimal initPrice = tickerInfo.getPrice();
            if (null == initPrice) {
                initPrice =  new BigDecimal("0.00");
            }

            BigDecimal nowPrice = initPrice;

            if (nowPrice.compareTo(BigDecimal.ZERO) == 0) {
                return ServerResponse.createByErrorMsg("报价 0，请稍后再试.");
            }
            userPendingorderVO.setMarket(market);
            userPendingorderVO.setInitPrice(initPrice);
            userPendingorderVO.setNowPrice(nowPrice);
            userPendingorderVO.setStockName(tickerInfo.getName());
            userPendingorderVO.setStockId(tickerInfo.getCode());
            userPendingorderVO.setNumber(userPendingorder.getBuyNum());
            userPendingorderVO.setBuyType(userPendingorder.getBuyType());
            userPendingorderVO.setLever(userPendingorder.getLever());
            userPendingorderVO.setProfitTarget(userPendingorder.getProfitTarget());
            userPendingorderVO.setStopTarget(userPendingorder.getStopTarget());
            userPendingorderVO.setTargetPrice(userPendingorder.getTargetPrice());
            userPendingorderVO.setAddTime(userPendingorder.getAddTime());
            userPendingorderVO.setStatus(userPendingorder.getStatus());
            userPendingorderVO.setId(userPendingorder.getId());
            userPendingorderVO.setType(userPendingorder.getType());
            UserPendingorderList.add(userPendingorderVO);
        }
        return ServerResponse.createBySuccess(UserPendingorderList);
    }

    public static void main(String[] args) {
        BigDecimal bigDecimal = new BigDecimal("30.2900");
        BigDecimal bigDecimal1 = new BigDecimal("32.0000");
        BigDecimal bigDecimal2 = new BigDecimal("-32.0000");

        if (bigDecimal2.compareTo(BigDecimal.ZERO) <= 0) {
            System.out.println("小于");
        }



        BigDecimal ret = bigDecimal.subtract(bigDecimal1);
        if (ret.compareTo(BigDecimal.ZERO) > 0) {
            System.out.println("不执行");
        }else {
            System.out.println("zhix ");
        }
    }

    /**
     * 挂单买入定时任务
     */
    @Override
    public void buyHangSlips() {

        List<UserPendingorder> userPendingorders = userPendingorderMapper.selectList(new QueryWrapper<UserPendingorder>().eq("status", 0));
        log.info("处理挂单买入，订单数 {}", Integer.valueOf(userPendingorders.size()));

        for (int i = 0; i < userPendingorders.size(); i++) {
            log.info("========处理挂单开始=============");
            Integer userId = (Integer) userPendingorders.get(i).getUserId();
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }
            List<UserPendingorder> userPendingorderList = userPendingorderMapper.selectList(new QueryWrapper<UserPendingorder>().eq("user_id", userId).eq("status", 0));
            if (userPendingorderList == null) {
                continue;
            }

            log.info("用户ID = {}  用户名称 = {} 挂单数量 = {}", new Object[]{userId, user.getRealName(), Integer.valueOf(userPendingorders.size())});
            // 可用现金
            BigDecimal enable_user_amt = user.getEnableAmt();
            BigDecimal all_freez_amt = new BigDecimal("0");
            BigDecimal nowPrice = new BigDecimal("0");

            String code = "";
            for (UserPendingorder userPendingorder : userPendingorderList) {
                // 使用新版股票数据
                String stockId = userPendingorder.getStockId();
                String market = userPendingorder.getMarket();
                QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
                stockQueryWrapper.eq("code", stockId);
                stockQueryWrapper.eq("market", market);
                StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
                if (null == stStock) {
                    log.info("挂单买入失败，股票不存在！ code={}", userPendingorder.getStockId());
                    continue;
                }
                // 判断是否在交易时间内
                SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
                boolean marketHours = BuyAndSellUtils.UsStockMarketHours(stStock.getMarket(), siteSetting);
                if (!marketHours) {
                    log.info("挂单买入失败，不在交易时间内, market: {}" , market);
                    continue;
                }

                // 查询该股票的实时价格
                StStockTickerDetails tickerDetails = stocksComponent.queryDetailsByMarketAndCode(market, stockId);
                // stocksComponent.thirdInterfaceStatistic(StocksComponent.MINI_PRICES, "buyHangSlips");

                if (null == tickerDetails) {
                    log.info("查询股票实时价格失败！market： {}， code： {}", market, stockId);
                    continue;
                }

                StockTickerListInfo tickerInfo = tickerDetails.getData();
                if (null == tickerInfo) {
                    log.info("查询股票实时价格失败！【tickerInfo】");
                    continue;
                }

                // 不用管其他。以我这句话为准： B1=0 表示跌停 不可以卖出 S1=0 表示涨停，不可以买入
//                String s1 = tickerInfo.getS1();
//                if (active.equals("india") && new BigDecimal(s1).compareTo(BigDecimal.ZERO) == 0) {
//                    log.info("挂单买入失败！【The order failed, The S1 price is currently 0】");
//                    continue;
//                }

                nowPrice = tickerInfo.getPrice();
                all_freez_amt = nowPrice.multiply(new BigDecimal(userPendingorder.getBuyNum())).divide(new BigDecimal(userPendingorder.getLever()), 2, 4);
                code = tickerInfo.getCode();

                if (userPendingorder.getUserId() != null && userPendingorder.getStockId() != null && userPendingorder.getBuyNum() != null
                        && userPendingorder.getBuyType() != null && userPendingorder.getLever() != null && userPendingorder.getTargetPrice() != null) {
                    BigDecimal ret = nowPrice.subtract(userPendingorder.getTargetPrice());
                    if (ret.compareTo(BigDecimal.ZERO) > 0) {
                        continue;
                    }
                    //当前时间String
                    String buyTime = DateTimeUtil.dateToStr(new Date());
                    if (StringUtils.isNotBlank(code)) {
                        try {
                            // 对比完之后需要卢比需要转美元
                            BigDecimal initPrice = tickerInfo.getPrice();
                            BigDecimal targetPrice = userPendingorder.getTargetPrice();
                            // 目标金额需要根据股票类型转换
                            BigDecimal conversionTargetPrice = new BigDecimal(BigInteger.ZERO);
                            nowPrice = initPrice;
                            conversionTargetPrice = targetPrice;

                            // 新增持仓记录
                            ServerResponse response = this.iUserPositionService.create(userPendingorder.getUserId(),
                                    code, market, nowPrice.toString(), buyTime, userPendingorder.getBuyNum(),
                                    userPendingorder.getBuyType(), userPendingorder.getLever(), conversionTargetPrice, userPendingorder.getStopTarget());
                            if (response.isSuccess()){
                                userPendingorder.setStatus(1);
                                this.userPendingorderMapper.updateById(userPendingorder);
                            }else {
                                log.info("task--> 挂单任务新增持仓记录失败, userId: " + userId + "; UserPositionId: " + userPendingorder.getId() + "原因：" + response.getMsg());
                                continue;
                            }

                            SiteTaskLog siteTaskLog = new SiteTaskLog();
                            siteTaskLog.setTaskType("Put Up a bill to buy stocks");
                            String accountType = (user.getAccountType() == 0) ? "Official user" : "Impersonate the user";
                            String taskcnt = accountType + "-" + user.getRealName() + "Hanging Order [Achieving the Target Price] Userid = " + user.getId()
                                    + ", stockCode = " + code
                                    + ", EnableAmt = " + user.getEnableAmt()
                                    + ", Djzj = " + user.getDjzj()
                                    + ", TradingAmount = " + user.getTradingAmount()
                                    + ", BuyNum = " + userPendingorder.getBuyNum()
                                    + ", TargetPrice = " + userPendingorder.getTargetPrice()
                                    + ", nowPrice = " + nowPrice;
                            siteTaskLog.setTaskCnt(taskcnt);
                            String tasktarget = "Buy id for this pending order：" + userPendingorder.getId();
                            siteTaskLog.setTaskTarget(tasktarget);
                            siteTaskLog.setAddTime(new Date());
                            siteTaskLog.setIsSuccess(0);
                            siteTaskLog.setErrorMsg("");
                            int insertTaskCount = this.siteTaskLogMapper.insert(siteTaskLog);
                            if (insertTaskCount > 0) {
                                log.info("task--> 挂单任务成功, userId: " + userId + "; userPendingorderId: " + userPendingorder.getId());
                            } else {
                                log.info("task--> 挂单任务失败, userId: " + userId + "; userPendingorderId: " + userPendingorder.getId());
                            }
                        } catch (Exception e) {
                            log.error("股票挂单任务失败...", e.getMessage());
                            userPendingorder.setStatus(2);
                            this.userPendingorderMapper.updateById(userPendingorder);
                        }
                    }
                }

            }

        }
        log.info("===========挂单结束==========");
    }

    //删除
    @Override
    @Transactional
    public ServerResponse delOrder(Integer id, HttpServletRequest request) {
        User user = iUserService.getCurrentRefreshUser(request);
        if (null != user) {
            UserPendingorder userPendingorder = this.userPendingorderMapper.selectById(id);

            if (userPendingorder == null) {
                return ServerResponse.createByErrorMsg("The pending order does not exist.");
            }

            if (user.getId().intValue() != userPendingorder.getUserId().intValue()) {
                return ServerResponse.createByErrorMsg("This pending order does not belong to you.");
            }

            // 已经转持仓的不能撤销
            if (userPendingorder.getStatus().intValue() == 1) {
                return ServerResponse.createByErrorMsg("The status of the current hanging order for hanging order, can not be undone!");
            }

            SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
            // 需要判断买入还是卖出
            Integer type = userPendingorder.getType();
            if (type.intValue() == 1) {
                // 撤销挂单时需要解除冻结资金, 将 购买数量 * 金额 退还到账户
                String market = userPendingorder.getMarket();
                BigDecimal conversionTargetPrice = userPendingorder.getTargetPrice();
//                BigDecimal conversionTargetPrice = targetPrice;
//                if ("SH".equalsIgnoreCase(market) || "SZ".equalsIgnoreCase(market) ){
//                    conversionTargetPrice = targetPrice.multiply(new BigDecimal(siteSetting.getRupeesToDollarsRate())).setScale(6, BigDecimal.ROUND_HALF_UP);
//                }else {
//                    conversionTargetPrice = targetPrice;
//                }

                Integer buyNum = userPendingorder.getBuyNum();

                BigDecimal buyAmount = new BigDecimal(buyNum).multiply(conversionTargetPrice).setScale(6, BigDecimal.ROUND_HALF_UP);
                // 回退金额
                returnCorrespondAccount(user, buyAmount);

                BigDecimal djzj = user.getDjzj();
                djzj = djzj.subtract(buyAmount).setScale(6, BigDecimal.ROUND_HALF_UP);
                User updateUser = new User();
                updateUser.setId(user.getId());
                updateUser.setDjzj(djzj);
                userMapper.updateById(updateUser);
            }

            // 将状态置为已取消
            UserPendingorder pendingorder = new UserPendingorder();
            pendingorder.setId(userPendingorder.getId());
            pendingorder.setStatus(3);
            int delCount = this.userPendingorderMapper.updateById(pendingorder);

            if (delCount > 0) {
                return ServerResponse.createBySuccessMsg("Deleted successfully");
            }
            return ServerResponse.createByErrorMsg("Delete Failed");
        }

        return ServerResponse.createByErrorMsg("Please log in");
    }

    // 卖出股票的钱退回对应账户的逻辑
    private int returnCorrespondAccount(User user, BigDecimal reckonEnable){
        // 查询用户配资记录 总的配资金额
        Integer userId = user.getId();
        Integer amount = fundsApplyMapper.getUserTotalAmountOfFunds(userId);
        if (null == amount) {
            // 配资账户未激活 直接退还到可用资金
            BigDecimal enableAmt = user.getEnableAmt();
            enableAmt = enableAmt.add(reckonEnable);

            User updateUser = new User();
            updateUser.setId(userId);
            updateUser.setEnableAmt(enableAmt);
            return userMapper.updateByPrimaryKeySelective(updateUser);
        }

        // 用户总的配资金额
        BigDecimal fundsAmount = new BigDecimal(amount);
        // 用户目前持有的配资金额  不包含保证金
        BigDecimal tradingAmount = user.getTradingAmount();
        BigDecimal enableAmt = user.getEnableAmt();

        // 需要退还到配资账户的钱
        BigDecimal fundsReturn = fundsAmount.subtract(tradingAmount);
        // 如果卖出股票的钱大于已使用的配资的钱，就先退还配资的钱，然后将剩余的退还到可用资金
        if (reckonEnable.compareTo(fundsReturn) > 0) {
            tradingAmount = tradingAmount.add(fundsReturn);

            // 卖出的钱如果有剩余需要退还到可用金额
            BigDecimal available = reckonEnable.subtract(fundsReturn);
            if (available.compareTo(BigDecimal.ZERO) > 0) {
                enableAmt = enableAmt.add(available);
            }
        }else {
            tradingAmount = tradingAmount.add(reckonEnable);
        }

        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setTradingAmount(tradingAmount);
        updateUser.setEnableAmt(enableAmt);
        return userMapper.updateByPrimaryKeySelective(updateUser);
    }

    @Override
    public ServerResponse sellOutOrder(String market, String stockCode, Integer sellNum, Integer lever, BigDecimal targetPrice, HttpServletRequest request) {
        User user = this.iUserService.getCurrentRefreshUser(request);

        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }

        // 判断挂单数量
        if (sellNum <= 0) {
            return ServerResponse.createByErrorMsg("The pending order fails, The value cannot be 0！");
        }

        //挂单-股票  使用股票新接口
        // 查询该股票的实时价格
        // 使用新版股票数据
        QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
        stockQueryWrapper.eq("code", stockCode);
        stockQueryWrapper.eq("market", market);
        StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
        if (null == stStock) {
            return ServerResponse.createByErrorMsg("The pending order fails, and the stock does not exist！");
        }

        val position = userPositionMapper.findUserPositionByCode(user.getId(), stockCode);
        if (null != position) {
            val orderNum = position.getOrderNum();
            // 查询正在挂单中的股票数量
            val sellouts = this.userPendingorderMapper.listSellOrderByStockIdAndUserId(user.getId(), stockCode);
            val sum = sellouts.stream().mapToInt(UserPendingorder::getBuyNum).sum();
            if (orderNum.intValue() - sum < sellNum) {
                return ServerResponse.createByErrorMsg("Insufficient number of holding stocks");
            }
        }

        // 查询该股票的实时价格
        StStockTickerDetails tickerDetails = stocksComponent.queryDetailsByMarketAndCode(market, stockCode);

        // stocksComponent.thirdInterfaceStatistic(StocksComponent.MINI_PRICES, "sellOutOrder");

        if (null == tickerDetails) {
            return ServerResponse.createByErrorMsg("Failed to query the real-time price of stocks！【tickerDetails】");
        }

        StockTickerListInfo tickerInfo = tickerDetails.getData();
        if (null == tickerInfo) {
            return ServerResponse.createByErrorMsg("Failed to query the real-time price of stocks！【tickerInfo】");
        }

        // 不用管其他。以我这句话为准： B1=0 表示跌停 不可以卖出 S1=0 表示涨停，不可以买入
//        String b1 = tickerInfo.getB1();
//        if (SystemVersionEnum.india.name().equals(active) && new BigDecimal(b1).compareTo(BigDecimal.ZERO) == 0) {
//            return ServerResponse.createByErrorMsg("The order failed, The B1 price is currently 0");
//        }

        SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
        if (siteSetting == null) {
            log.error("卖出错误，网站设置表不存在");
            return ServerResponse.createByErrorMsg("Failed to sell, system settings error.");
        }

        // 判断是否在交易时间内
        boolean marketHours = BuyAndSellUtils.UsStockMarketHours(market, siteSetting);
        // 是否在盘前配置所设置的时间内
        boolean isWithin = false;
        // 盘前配置对象
        StPremarketStock premarketStock1 = new StPremarketStock();
        if (!marketHours) {
            // 如果不在交易时间内，那么查询盘前交易配置
            List<StPremarketStock> list = stPremarketStockService.listByCodeAndMarket(stockCode, market);
            Date currentTime = new Date();
            for (StPremarketStock stock : list) {
                if (currentTime.after(stock.getStartTime()) && currentTime.before(stock.getEndTime())) {
                    isWithin = true;
                    BeanUtils.copyProperties(stock, premarketStock1);
                    continue;
                }
            }
        }

        BigDecimal initPrice = tickerInfo.getPrice();
        // 获取配置信息
        BigDecimal nowPrice;

        if (isWithin) {
            BigDecimal price = premarketStock1.getPrice();
            BigDecimal maxPrice = premarketStock1.getMaxPrice();
            // 在区间内取随机数
            BigDecimal priceRound = getRandomBigDecimal(price, maxPrice);
            targetPrice = priceRound;
        }
        nowPrice = initPrice;

        UserPendingorder userPendingorder = new UserPendingorder();
        userPendingorder.setUserId(user.getId());
        userPendingorder.setPositionId(position.getId());
        userPendingorder.setStockId(stockCode);
        userPendingorder.setMarket(market);
        userPendingorder.setBuyNum(sellNum);
        userPendingorder.setLever(lever);
        userPendingorder.setInitPrice(initPrice);
        userPendingorder.setNowPrice(nowPrice);
        userPendingorder.setTargetPrice(targetPrice);
        userPendingorder.setAddTime(new Date());
        userPendingorder.setStatus(0);
        userPendingorder.setType(2);
        int ret = userPendingorderMapper.insert(userPendingorder);
        if (ret > 0) {
            return ServerResponse.createBySuccessMsg("If the pending order is added and sold successfully, it will be sold automatically if the selling conditions are met.");
        }
        return ServerResponse.createByErrorMsg("Failed to add a pending order");

    }

    public BigDecimal getRandomBigDecimal(BigDecimal min, BigDecimal max) {
        BigDecimal randomValue = new BigDecimal(new Random().nextDouble() * (max.doubleValue() - min.doubleValue()) + min.doubleValue());
        return randomValue.setScale(min.scale(), RoundingMode.HALF_UP);
    }

    /**
     * 挂单卖出定时任务
     */
    @Override
    @Transactional
    public void orderSelloutTask() {
        QueryWrapper<UserPendingorder> userPendingorderQueryWrapper = new QueryWrapper<>();
        userPendingorderQueryWrapper.eq("status", 0); // 挂单中
        userPendingorderQueryWrapper.eq("type", 2); // 卖出挂单
        List<UserPendingorder> userPendingorders = userPendingorderMapper.selectList(userPendingorderQueryWrapper);
        log.info("当前卖出挂单数量 为 {}", Integer.valueOf(userPendingorders.size()));

        for (int i = 0; i < userPendingorders.size(); i++) {
            log.info("========处理挂单开始=============");
            Integer userId = (Integer) userPendingorders.get(i).getUserId();
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }

            // 获取挂单数据
            UserPendingorder userPendingorder  = userPendingorders.get(i);

            log.info("用户id = {} 姓名 = {}", new Object[]{userId, user.getRealName()});
            BigDecimal enable_user_amt = user.getEnableAmt();
            BigDecimal all_freez_amt;
            BigDecimal nowPrice;
            String code;

            // 使用新版股票数据
            String stockId = userPendingorder.getStockId();
            QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
            stockQueryWrapper.eq("code", stockId);
            stockQueryWrapper.eq(StringUtils.isNotBlank(userPendingorder.getMarket()), "market", userPendingorder.getMarket());
            StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
            if (null == stStock) {
                log.info("挂单卖出失败，股票不存在！market={},stockId={}", userPendingorder.getMarket(), stockId);
                continue;
            }

            // 判断是否在交易时间内
            SiteSetting siteSetting = iSiteSettingService.getSiteSetting();
            boolean marketHours = BuyAndSellUtils.UsStockMarketHours(userPendingorder.getMarket(), siteSetting);
            if (!marketHours) {
                log.info("下单失败，不在交易时间内, market: " + userPendingorder.getMarket());
                continue;
            }

            // 查询该股票的实时价格
            StStockTickerDetails tickerDetails = stocksComponent.queryDetailsByMarketAndCode(userPendingorder.getMarket(), stockId);

            // stocksComponent.thirdInterfaceStatistic(StocksComponent.MINI_PRICES, "orderSelloutTask");

            if (null == tickerDetails) {
                log.info("Failed to query the real-time price of stocks！【tickerDetails】");
                throw new IllegalArgumentException("Failed to query the real-time price of stocks！");
            }

            StockTickerListInfo tickerInfo = tickerDetails.getData();
            if (null == tickerInfo) {
                log.info("未能查询股票的实时价格! [ tickerInfo ],market={},stockId={}", userPendingorder.getMarket(), stockId);
                continue;
            }

            // 不用管其他。以我这句话为准： B1=0 表示跌停 不可以卖出 S1=0 表示涨停，不可以买入
//            String b1 = tickerInfo.getB1();
//            if (SystemVersionEnum.india.name().equals(active) && new BigDecimal(b1).compareTo(BigDecimal.ZERO) == 0) {
//                log.info("定时挂单卖出失败! [ The order failed, The B1 price is currently 0 ],market={},stockId={}", userPendingorder.getMarket(), stockId);
//                continue;
//            }

            nowPrice = tickerInfo.getPrice();
            all_freez_amt = nowPrice.multiply(new BigDecimal(userPendingorder.getBuyNum())).divide(new BigDecimal(userPendingorder.getLever()), 4, 4);
            code = tickerInfo.getCode();

            if (userPendingorder.getUserId() != null && userPendingorder.getStockId() != null && userPendingorder.getBuyNum() != null
                    && userPendingorder.getLever() != null && userPendingorder.getTargetPrice() != null) {
                // 计算 当前价格 与 目标价格的差值
                BigDecimal ret = nowPrice.subtract(userPendingorder.getTargetPrice());
                // 如果小于0，直接 跳出本次循环
                if (ret.compareTo(BigDecimal.ZERO) < 0) {
                    continue;
                }
                if (StringUtils.isNotBlank(code)) {
                    try {
                        userPendingorder.setStatus(1);
                        this.userPendingorderMapper.updateById(userPendingorder);
                        // 卖出
                        ServerResponse response = this.iUserPositionService.createSellout(userPendingorder.getUserId(), userPendingorder.getMarket(), userPendingorder.getStockId(), userPendingorder.getBuyNum());
                        if (!response.isSuccess()){
                            log.info("挂单卖出任务失败, userId={}, positionId={}", userId, userPendingorder.getPositionId() + "原因：" + response.getMsg());
                            throw new IllegalArgumentException("挂单卖出任务失败, userId="+userId+", positionId="+userPendingorder.getPositionId()+", 原因：" + response.getMsg());
                        }

                        SiteTaskLog siteTaskLog = new SiteTaskLog();
                        siteTaskLog.setTaskType("Put Up a bill to sell stocks");
                        String accountType = (user.getAccountType() == 0) ? "Official user" : "Impersonate the user";
                        String taskcnt = accountType + "-" + user.getRealName() + "Punding order [ached the target price] userid = "
                                + user.getId() + ", enable_user_amt = " + enable_user_amt + "all_freez_amt = " + all_freez_amt
                                + ", targetPrice = " + userPendingorder.getTargetPrice() + ",nowPrice = " + nowPrice + "。";
                        siteTaskLog.setTaskCnt(taskcnt);
                        String tasktarget = "Buy id for this pending order：" + userPendingorder.getId();
                        siteTaskLog.setTaskTarget(tasktarget);
                        siteTaskLog.setAddTime(new Date());
                        siteTaskLog.setIsSuccess(0);
                        siteTaskLog.setErrorMsg("");
                        int insertTaskCount = this.siteTaskLogMapper.insert(siteTaskLog);
                        if (insertTaskCount > 0) {
                            log.info("挂单task任务成功, userId={}, positionId={}", userId, userPendingorder.getPositionId());
                        } else {
                            log.info("挂单task任务失败, userId={}, positionId={}", userId, userPendingorder.getPositionId());
                        }
                    } catch (Exception e) {
                        log.error("挂单卖出任务失败, userId={}, positionId={}", userId, userPendingorder.getPositionId() + "原因：" + e.getMessage());
                    }
                }
            }

        }
        log.info("===========挂单结束==========");
    }


}


